A .NET Web Service Example

For many years, .NET programmers have created web services using the ASP.NET Web Service project template of Visual Studio, which can be accessed using the File > New > Web Site dialog box. This particular project template creates a commonly used directory structure and a handful of initial files to represent the web service itself. While this project template is helpful in getting you up and running, you can build a .NET XML web service with a simple text editor and test it immediately with the ASP.NET development web server (Chapter 32 examines this utility in more detail).

For example, assume you have authored the following programming logic in a new file named HelloWebService.asmx (*.asmx is the default file extension for a .NET XML web service file). Once you do this, save it into a folder such as C:\HelloWebService:

<%@ WebService Language="C#" Class="HelloWebService" %>
using System;
using System.Web.Services;

public class HelloWebService
{
    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }
}

While this simple service doesn’t do anything particularly useful, notice that the file opens with the <%@WebService%> directive, which you use to specify which .NET programming language the file uses and the name of the class type that represents the service. Beyond this, the only point of interest is that you decorate the HelloWorld() method with the [WebMethod] attribute. In many cases, this is all you need to do to expose a method to external callers using HTTP. Finally, notice that you do not need to do anything special to encode the return value into XML because the runtime does this automatically.

If you wish to test this web service, simply press the F5 key to start a debugging session or Ctrl+F5 to run the project. At this point, your browser should launch, showing each web method exposed from this endpoint. At this point, you can click the HelloWorld link to invoke the method using HTTP. Once you do this, the browser displays the return value encoded as XML:

<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">
    Hello World
</string>

Simple stuff, right? Even better, when you wish to build a “real” client to communicate with the service, you can generate a client-side proxy that you can use to invoke web methods. As you might know, a proxy is a class that encapsulates the low-level details of communicating with another object; in this case, that is the service itself.

You can generate proxies for a classic XML web service in two ways. First, you can use the command-line tool, wsdl.exe, which is useful when you want full control over how the proxy is generated. Second, you can simplify matters by using Visual Studio’s Add Web Reference option under the Project menu. Both of these approaches also generate a required client-side *.config file, which contains various configuration settings for the proxy (such as the web service location).

Assuming you have generated a proxy for this simple web service (you don’t need to do so here), the client application can invoke the web method in a simple manner:

static void Main(string[] args)
{
    // The proxy type contains code to read the *.config file
    // to resolve the location of the web service.
    HelloWebServiceProxy proxy = new HelloWebServiceProxy();
    Console.WriteLine(proxy.HelloWorld());
    Console.ReadLine();
}

While it remains possible to build this traditional flavor of XML web service under .NET 4.0, most new service projects will benefit from using the WCF templates instead. In fact, WCF is the preferred manner to build service-oriented systems since the release of .NET 3.0.

Source Code You can find the HelloWorldWebService project under the Chapter 25 subdirectory.

Web Service Standards

A major problem that web services faced early on was the fact that all of the big industry players (e.g., Microsoft, IBM, and Sun Microsystems) created web service implementations that were not 100-percent compatible with other web service implementations. Obviously, this was an issue because the whole point of web services is to achieve a high degree of interoperability across platforms and operating systems!

To ensure the interoperability of web services, groups such as the World Wide Web Consortium (W3C: www.w3.org) and the Web Services Interoperability Organization (WS-I: www.ws-i.org) began to author several specifications that laid out how a software vendor (e.g., IBM, Microsoft, or Sun Microsystems) should build web service–centric software libraries to ensure compatibility.

Collectively, all of these specifications are given the blanket name WS-*, and they cover such issues as security, attachments, the description of web services (using the Web Service Description Language, or WSDL), policies, SOAP formats, and a slew of other important details.

Microsoft’s implementation of most of these standards (for both managed and unmanaged code) is embodied in the Web Services Enhancements (WSE) toolkit, which you can download for free from the supporting website: http://msdn2.microsoft.com/en-us/webservices.

When you build WCF service applications, you do not need to use the assemblies that are part of the WSE toolkit directly. Rather, if you build a WCF service that uses an HTTP-based binding (you’ll learn more details about this later in the chapter), these same WS-* specifications are given to you out of the box (exactly which ones depend on the binding you choose).

Named Pipes, Sockets, and P2P

As if choosing from DCOM, .NET remoting, web services, COM+, and MSMQ were not challenging enough, the list of distributed APIs continues. Programmers can also use additional interprocess communication APIs such as named pipes, sockets, and peer-to-peer (P2P) services. These lower-level APIs typically provide better performance (especially for machines on the same LAN); however, using these APIs becomes more complex (if not impossible) for outward-facing applications.

If you build a distributed system involving a set of applications running on the same physical machine, you can use the named pipes API with the System.IO.Pipes namespace. This approach can provide the absolute fastest way to push data between applications on the same machine.

Also, if you build an application that requires absolute control over how network access is obtained and maintained, you can implement sockets and P2P functionality under the .NET platform using the System.Net.Sockets and System.Net.PeerToPeer namespaces, respectively.